package failover

import (
	"context"
	"sync/atomic"
	"webook/internal/service/sms"
)

type TimeoutFailOverSMSService struct {
	svcs      []sms.Service
	idx       int32 //当前使用的下标
	cnt       int32 //连续几个超时
	threshold int32 //阈值 只读
}

func NewTimeoutFailOverSMSService(svcs []sms.Service, threshold int32) *TimeoutFailOverSMSService {
	return &TimeoutFailOverSMSService{
		svcs:      svcs,
		threshold: threshold,
	}
}

func (f *TimeoutFailOverSMSService) Send(ctx context.Context, tplId string, args []string, numbers ...string) error {
	idx := atomic.LoadInt32(&f.idx)
	cnt := atomic.LoadInt32(&f.cnt)
	//超过阈值 执行切换
	if cnt >= f.threshold {
		newIdx := (idx + 1) % int32(len(f.svcs))
		if atomic.CompareAndSwapInt32(&f.idx, idx, newIdx) { //多个线程切换
			//重置cnt
			atomic.StoreInt32(&f.cnt, 0)
		}
		idx = newIdx
	}

	svc := f.svcs[idx]
	err := svc.Send(ctx, tplId, args, numbers...)
	switch err {
	case nil:
		//连续超时 所以不超时的时候要设置为0
		atomic.StoreInt32(&f.cnt, 0)
		return nil
	case context.DeadlineExceeded:
		atomic.AddInt32(&f.cnt, 1)
	default:
		//遇到了错误但是不是超时错误
		//如果强调一定是超时，就不增加cnt
		//如果是EOF之类的错误，可以直接切换
	}
	return err
}
